package com.example.itas;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Intent;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.example.classes.IP;
import com.example.classes.Pcroomlist;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnInfoWindowClickListener;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class MapActivity extends Activity implements LocationListener,
		OnClickListener {
	private GoogleMap map;
	double latitude, longitude;
	double current_lat, current_lon;
	private LocationManager locationManager;
	private String add = "";
	Geocoder gc;
	private boolean camera_flag = true;

	private final String TAG = "MapActivity";

	IP ip = new IP();
	private final String HOST = ip.ip;
	private final int PORT = 8080;
	private final String PATH = "/IServer-war/webresources/connecting";
	private final String PATH_GET = "/IServer-war/webresources/entities.pcroomlist/getPcroom";

	Map<Marker, Pcroomlist> markers = new HashMap<Marker, Pcroomlist>();

	EditText address;
	Button search, here;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_map);

		address = (EditText) findViewById(R.id.map_et_add);
		search = (Button) findViewById(R.id.map_btn_search);
		search.setOnClickListener(this);
		here = (Button) findViewById(R.id.map_btn_here);
		here.setOnClickListener(this);

		locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		// Criteria criteria = new Criteria();
		// provider = locationManager.getBestProvider(criteria, true);

		Location lastLocation = locationManager
				.getLastKnownLocation(LocationManager.GPS_PROVIDER);

		map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map))
				.getMap();

		if (lastLocation != null)
			onLocationChanged(lastLocation);

		ConnectingGet cg = new ConnectingGet();
		cg.execute();
		AsyncGet ag = new AsyncGet();
		ag.execute();
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				5000, 10, this);
	}

	private class ConnectingGet extends AsyncTask<Void, Void, String> {

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
		}

		@Override
		protected String doInBackground(Void... params) {
			HttpHost target = new HttpHost(HOST, PORT);
			HttpClient client = new DefaultHttpClient();
			HttpGet get = new HttpGet(PATH);

			// set the MIME type for POST message body.
			get.setHeader("Content-Type", "application/json");

			HttpEntity entity = null;
			try {
				HttpResponse response = client.execute(target, get);
				Log.d(TAG, "in ConnectingGet: "
						+ response.getStatusLine().getStatusCode());
				if (response.getStatusLine().getStatusCode() != 200)
					return null;

				entity = response.getEntity();
				// String str = entity.toString();
				String str = EntityUtils.toString(entity, "utf-8");
				return str;
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(String result) {
			if (result != null) {
				Toast.makeText(getApplicationContext(),
						"Success to connect!: " + result, Toast.LENGTH_SHORT)
						.show();
				Log.d(TAG, "in ConnectingGet: success");
			} else {
				Toast.makeText(getApplicationContext(), "Fail to connect!",
						Toast.LENGTH_SHORT).show();
				Log.d(TAG, "in ConnectingGet: fail");
			}
		}
	}

	private class AsyncGet extends AsyncTask<Void, Void, List<Pcroomlist>> {

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
		}

		@Override
		protected List<Pcroomlist> doInBackground(Void... params) {
			HttpHost target = new HttpHost(HOST, PORT);
			HttpClient client = new DefaultHttpClient();
			HttpGet get = new HttpGet(PATH_GET);

			// set the MIME type for POST message body.
			get.setHeader("Content-Type", "application/json");

			HttpEntity entity = null;
			try {
				HttpResponse response = client.execute(target, get);
				Log.d(TAG, "" + response.getStatusLine().getStatusCode());
				if (response.getStatusLine().getStatusCode() != 200)
					return null;

				entity = response.getEntity();
				String str = EntityUtils.toString(entity, "utf-8");
				Log.d(TAG, str);
				List<Pcroomlist> p = JSONtoPcroom(str);
				return p;
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(List<Pcroomlist> result) {
			if (result != null) {
				Toast.makeText(getApplicationContext(),
						"Success to get buildings!", Toast.LENGTH_SHORT).show();
				for (Pcroomlist p : result) {
					LatLng latlng = new LatLng(p.getLatitude(),
							p.getLongitude());

					Marker marker = map
							.addMarker(new MarkerOptions()
									.position(latlng)
									.title(p.getName())
									.snippet(
											"Address: " + p.getAddress() + "\n"
													+ "Telephone: "
													+ p.getTel())
									.icon(BitmapDescriptorFactory
											.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)));

					markers.put(marker, p);

					map.setOnInfoWindowClickListener(new OnInfoWindowClickListener() {

						public void onInfoWindowClick(Marker arg0) {
							Intent intent = new Intent(MapActivity.this,
									RoominfoActivity.class);
							intent.putExtra("NAME", markers.get(arg0).getName());
							intent.putExtra("ADDRESS", markers.get(arg0)
									.getAddress());
							intent.putExtra("TELEPHONE", markers.get(arg0)
									.getTel());
							intent.putExtra("ID", markers.get(arg0).getId());
							Log.d(TAG, markers.get(arg0).getId() + "");
							startActivity(intent);
						}
					});

				}
			} else {
				Toast.makeText(getApplicationContext(),
						"Fail to get PC Rooms!", Toast.LENGTH_SHORT).show();
			}
		}
	}

	private List<Pcroomlist> JSONtoPcroom(String json) {
		Gson gson = new Gson();
		Type t = new TypeToken<List<Pcroomlist>>() {
		}.getType();
		List<Pcroomlist> p = gson.fromJson(json, t);
		return p;
	}

	private class AsyncSearch extends AsyncTask<Void, Void, LatLng> {

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
		}

		@Override
		protected LatLng doInBackground(Void... params) {
			HttpClient client = new DefaultHttpClient();
			try {
				HttpGet get = new HttpGet(
						"http://maps.googleapis.com/maps/api/geocode/json?address="
								+ URLEncoder.encode(add, "UTF-8") + "&sensor=true&language=ko");

				// set the MIME type for POST message body.
				get.setHeader("Content-Type", "application/json");

				HttpEntity entity = null;
				HttpResponse response = client.execute(get);
				Log.d(TAG, "" + response.getStatusLine().getStatusCode());
				if (response.getStatusLine().getStatusCode() != 200)
					return null;

				entity = response.getEntity();
				String str = EntityUtils.toString(entity, "utf-8");
				JSONObject jsonObject = new JSONObject(str);
				latitude = ((JSONArray) jsonObject.get("results"))
						.getJSONObject(0).getJSONObject("geometry")
						.getJSONObject("location").getDouble("lat");
				longitude = ((JSONArray) jsonObject.get("results"))
						.getJSONObject(0).getJSONObject("geometry")
						.getJSONObject("location").getDouble("lng");

				LatLng result = new LatLng(latitude, longitude);

				return result;
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(LatLng result) {
			if (result != null) {
				Toast.makeText(getApplicationContext(),
						"Success to search: " + result.toString(),
						Toast.LENGTH_SHORT).show();
				Log.d(TAG, result.toString());

				camera_flag = false;
				LatLng address = new LatLng(latitude, longitude);
				CameraPosition cp = new CameraPosition.Builder()
						.target(address).zoom(18).build();

				map.animateCamera(CameraUpdateFactory.newCameraPosition(cp));
			} else {
				Toast.makeText(getApplicationContext(), "Fail to search!",
						Toast.LENGTH_SHORT).show();
			}
		}
	}

	public void onLocationChanged(Location arg0) {
		// TODO Auto-generated method stub
		current_lat = arg0.getLatitude();
		current_lon = arg0.getLongitude();

		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
				5000, 10, this);

		LatLng address = new LatLng(current_lat, current_lon);
		CameraPosition cp = new CameraPosition.Builder().target(address)
				.zoom(18).build();

		if (camera_flag) {
			map.animateCamera(CameraUpdateFactory.newCameraPosition(cp));
			camera_flag = !camera_flag;
		}
	}

	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub

	}

	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub

	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub

	}

	public void onClick(View v) {
		if (v.getId() == R.id.map_btn_search) {
			camera_flag = false;
			add = address.getText().toString();
			AsyncSearch as = new AsyncSearch();
			as.execute();
		} else if (v.getId() == R.id.map_btn_here) {
			camera_flag = true;
		}
	}
	
	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }	
	
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		switch(item.getItemId())
		{
			case R.id.menu_settings:
				Intent intent = new Intent(MapActivity.this, SettingsActivity.class);
				startActivity(intent);
			break;
		
		}
		return true;
	}

}
